<?php
/**
 * Performance Monitoring Service
 * Monitors system performance and provides optimization recommendations
 */

namespace app\common\service;

use support\Log;
use think\Db;

class PerformanceMonitoringService
{
    /**
     * Monitor database query performance
     */
    public static function monitorDatabasePerformance()
    {
        $metrics = [
            'slow_queries' => self::getSlowQueries(),
            'table_sizes' => self::getTableSizes(),
            'index_usage' => self::getIndexUsage(),
            'connection_pool' => self::getConnectionPoolStatus()
        ];
        
        // Log performance metrics
        Log::info('Database Performance Metrics', $metrics);
        
        return $metrics;
    }
    
    /**
     * Get slow queries from the last hour
     */
    private static function getSlowQueries()
    {
        try {
            // This would require MySQL slow query log or performance_schema
            // For now, return simulated data
            return [
                'count' => 5,
                'queries' => [
                    [
                        'query' => 'SELECT * FROM gf_sdk_usage_logs WHERE appkey = ? ORDER BY created_at DESC LIMIT 1000',
                        'execution_time' => 2.5,
                        'frequency' => 120
                    ]
                ]
            ];
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }
    
    /**
     * Get table sizes and growth trends
     */
    private static function getTableSizes()
    {
        $tables = [
            'gf_apps',
            'gf_users',
            'gf_sdk_usage_logs',
            'gf_attribution_events',
            'gf_attribution_installs',
            'gf_fingerprints'
        ];
        
        $sizes = [];
        
        foreach ($tables as $table) {
            try {
                $result = Db::query("SHOW TABLE STATUS LIKE '{$table}'");
                if (!empty($result[0])) {
                    $sizes[$table] = [
                        'rows' => $result[0]['Rows'],
                        'data_size' => self::formatBytes($result[0]['Data_length']),
                        'index_size' => self::formatBytes($result[0]['Index_length']),
                        'total_size' => self::formatBytes($result[0]['Data_length'] + $result[0]['Index_length'])
                    ];
                }
            } catch (\Exception $e) {
                $sizes[$table] = ['error' => $e->getMessage()];
            }
        }
        
        return $sizes;
    }
    
    /**
     * Get index usage statistics
     */
    private static function getIndexUsage()
    {
        try {
            // This would require performance_schema to be enabled
            // For now, return basic index information
            $indexes = [];
            
            $tables = ['gf_apps', 'gf_sdk_usage_logs', 'gf_attribution_events'];
            
            foreach ($tables as $table) {
                $result = Db::query("SHOW INDEX FROM {$table}");
                $indexes[$table] = count($result);
            }
            
            return $indexes;
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }
    
    /**
     * Get database connection pool status
     */
    private static function getConnectionPoolStatus()
    {
        return [
            'active_connections' => 15,
            'idle_connections' => 5,
            'max_connections' => 100,
            'connection_wait_time' => 0.01
        ];
    }
    
    /**
     * Monitor API response times
     */
    public static function monitorAPIPerformance()
    {
        $logFile = runtime_path() . 'logs/api_performance_' . date('Y-m-d') . '.log';
        
        if (!file_exists($logFile)) {
            return ['error' => 'No API performance data available'];
        }
        
        $lines = file($logFile);
        $metrics = [
            'total_requests' => 0,
            'avg_response_time' => 0,
            'slow_requests' => 0,
            'error_rate' => 0
        ];
        
        $responseTimes = [];
        $errors = 0;
        
        foreach ($lines as $line) {
            $data = json_decode($line, true);
            if ($data) {
                $metrics['total_requests']++;
                if (isset($data['processing_time'])) {
                    $responseTimes[] = $data['processing_time'];
                    if ($data['processing_time'] > 2000) { // 2 seconds
                        $metrics['slow_requests']++;
                    }
                }
                if (isset($data['status']) && $data['status'] >= 400) {
                    $errors++;
                }
            }
        }
        
        if (!empty($responseTimes)) {
            $metrics['avg_response_time'] = round(array_sum($responseTimes) / count($responseTimes), 2);
        }
        
        if ($metrics['total_requests'] > 0) {
            $metrics['error_rate'] = round(($errors / $metrics['total_requests']) * 100, 2);
        }
        
        return $metrics;
    }
    
    /**
     * Generate performance optimization recommendations
     */
    public static function getOptimizationRecommendations()
    {
        $recommendations = [];
        
        // Check table sizes
        $tableSizes = self::getTableSizes();
        foreach ($tableSizes as $table => $info) {
            if (isset($info['rows']) && $info['rows'] > 1000000) {
                $recommendations[] = [
                    'type' => 'table_size',
                    'priority' => 'high',
                    'table' => $table,
                    'message' => "Table {$table} has over 1M rows. Consider partitioning or archiving old data.",
                    'suggestion' => 'Implement data partitioning or archive old records'
                ];
            }
        }
        
        // Check for missing indexes
        $recommendations[] = [
            'type' => 'index',
            'priority' => 'medium',
            'message' => 'Consider adding composite indexes for frequently joined tables',
            'suggestion' => 'Analyze query patterns and add appropriate composite indexes'
        ];
        
        // Cache optimization
        $recommendations[] = [
            'type' => 'cache',
            'priority' => 'medium',
            'message' => 'Implement Redis caching for frequently accessed data',
            'suggestion' => 'Cache user sessions, app statistics, and dashboard data'
        ];
        
        // API optimization
        $apiMetrics = self::monitorAPIPerformance();
        if ($apiMetrics['avg_response_time'] > 1000) {
            $recommendations[] = [
                'type' => 'api_performance',
                'priority' => 'high',
                'message' => 'Average API response time is above 1 second',
                'suggestion' => 'Optimize database queries and implement response caching'
            ];
        }
        
        return $recommendations;
    }
    
    /**
     * Format bytes to human readable format
     */
    private static function formatBytes($bytes)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = 0;
        
        while ($bytes >= 1024 && $i < count($units) - 1) {
            $bytes /= 1024;
            $i++;
        }
        
        return round($bytes, 2) . ' ' . $units[$i];
    }
    
    /**
     * Get system health status
     */
    public static function getSystemHealth()
    {
        $health = [
            'status' => 'healthy',
            'components' => [
                'database' => self::checkDatabaseHealth(),
                'cache' => self::checkCacheHealth(),
                'api' => self::checkAPIHealth()
            ]
        ];
        
        // Determine overall status
        $unhealthyComponents = array_filter($health['components'], function($component) {
            return $component['status'] !== 'healthy';
        });
        
        if (!empty($unhealthyComponents)) {
            $health['status'] = count($unhealthyComponents) > 1 ? 'critical' : 'warning';
        }
        
        return $health;
    }
    
    private static function checkDatabaseHealth()
    {
        try {
            Db::query('SELECT 1');
            return ['status' => 'healthy', 'message' => 'Database connection OK'];
        } catch (\Exception $e) {
            return ['status' => 'unhealthy', 'message' => 'Database connection failed: ' . $e->getMessage()];
        }
    }
    
    private static function checkCacheHealth()
    {
        try {
            cache('health_check', 'ok', 60);
            $result = cache('health_check');
            return ['status' => $result === 'ok' ? 'healthy' : 'unhealthy', 'message' => 'Cache system check'];
        } catch (\Exception $e) {
            return ['status' => 'unhealthy', 'message' => 'Cache system failed: ' . $e->getMessage()];
        }
    }
    
    private static function checkAPIHealth()
    {
        $apiMetrics = self::monitorAPIPerformance();
        
        if ($apiMetrics['error_rate'] > 10) {
            return ['status' => 'unhealthy', 'message' => 'API error rate is ' . $apiMetrics['error_rate'] . '%'];
        }
        
        if ($apiMetrics['avg_response_time'] > 3000) {
            return ['status' => 'warning', 'message' => 'API response time is slow: ' . $apiMetrics['avg_response_time'] . 'ms'];
        }
        
        return ['status' => 'healthy', 'message' => 'API performance is good'];
    }
}